package com.sentinel.demo.config;

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import com.alibaba.csp.sentinel.slots.block.Rule;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.crypto.spec.DESedeKeySpec;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: SpringBootDemos
 * @description:
 * @author: Kangsen
 * @create: 2021-10-22 10:43
 **/
@Configuration
public class SentinelConfig {

    /**
     * 对资源限流
     * @return
     */
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){
        return new SentinelResourceAspect();
    }

    /**
     * resource	资源名，即规则的作用对象
     * grade	熔断策略，支持慢调用比例/异常比例/异常数策略	慢调用比例
     * count	慢调用比例模式下为慢调用临界 RT（超出该值计为慢调用）；异常比例/异常数模式下为对应的阈值
     * timeWindow	熔断时长，单位为 s
     * minRequestAmount	熔断触发的最小请求数，请求数小于该值时即使异常比率超出阈值也不会熔断（1.7.0 引入）	5
     * statIntervalMs	统计时长（单位为 ms），如 60*1000 代表分钟级（1.8.0 引入）	1000 ms
     * slowRatioThreshold	慢调用比例阈值，仅慢调用比例模式有效（1.8.0 引入）
     * 手工设置设置限流规则
     */
    @PostConstruct
    private void initFlowRules() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule flowRule = new FlowRule();
        flowRule.setResource("sayHello");//资源路径
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);//限流阈值类型：0线程数  1：QPS 每秒访问量
        flowRule.setCount(2);//限流阈值 超出就异常
        //flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); //对超出阈值的请求处理方式：0直接拒绝 1 warm up 2匀速排队
        //flowRule.setStrategy(RuleConstant.STRATEGY_CHAIN);//调用关系限流策略，0：根据调用方限流、1根据调用链路入口限流 2据有关系的资源限流
        //flowRule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT);//调用来源 default:不区分来源调用者   some_origin_name 针对特定的调用者
        rules.add(flowRule);

        flowRule = new FlowRule();
        flowRule.setResource("say");
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        flowRule.setCount(1);
        rules.add(flowRule);

        FlowRuleManager.loadRules(rules);

        //降级规则 多个degreadeRule
        List<DegradeRule> degradeRules = new ArrayList<>();
        DegradeRule degradeRule = new DegradeRule();
        //创建第一个根据响应时间熔断降级
        degradeRule.setResource("circuitBreaker0");
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);//配置降级规则  0平均响应时间  1:根据失败占比  2:失败次数
        degradeRule.setCount(0.6);//结合规则  失败次数到达后 熔断
        degradeRule.setTimeWindow(2);//达到条件后再timeWindow 指定时间段都不允许pass
        degradeRules.add(degradeRule);

        //根据失败占比降级
        degradeRule.setResource("circuitBreaker1");
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);//配置降级规则  0平均响应时间  1:根据失败占比  2:失败次数
        degradeRule.setCount(0.5);//结合规则  失败次数到达后 熔断
        degradeRule.setTimeWindow(2);//达到条件后再timeWindow 指定时间段都不允许pass
        degradeRules.add(degradeRule);

        //根据失败次数降级
        degradeRule.setResource("circuitBreaker2");
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);//配置降级规则  0平均响应时间  1:根据失败占比  2:失败次数
        degradeRule.setCount(2);//结合规则  失败次数到达后 熔断
        degradeRule.setTimeWindow(2);//达到条件后再timeWindow 指定时间段都不允许pass
        degradeRules.add(degradeRule);


        DegradeRuleManager.loadRules(degradeRules);

    }
}
